package com.example.stock.entity.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.stock.comm.FreqEnum;
import com.example.stock.comm.StrategyEnum;
import com.example.stock.entity.eo.StatParamEo;
import com.example.stock.entity.eo.StockStatEo;
import com.example.stock.entity.mapper.StockStatMapper;
import com.example.stock.entity.service.IStatParamService;
import com.example.stock.entity.service.IStockStatService;
import com.example.stock.entity.service.IStockTradeService;
import com.example.stock.service.IServiceCalc;
import com.example.stock.vo.DataVo;
import com.example.stock.vo.common.TradeVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class StockStatServiceImpl extends ServiceImpl<StockStatMapper, StockStatEo> implements IStockStatService {

    @Resource
    private IStockTradeService stockTradeService;
    @Resource
    private IServiceCalc serviceCalc;
    @Resource
    private IStatParamService statParamService;

    public Double analysisEmaUp(int m, int n, List<DataVo> closeData, boolean save, String tsCode, FreqEnum freq) {
        StrategyEnum strategyEnum = StrategyEnum.EMA_UP;
        List<TradeVo> tradeVos = serviceCalc.doCalcOne(closeData, m, n,strategyEnum);
        tradeVos = tradeVos.stream().skip(50).collect(Collectors.toList());
        Double aDouble = stockTradeService.doTrade(tradeVos, save,tsCode, strategyEnum);

        if (save) {
            StatParamEo eo = new StatParamEo();
            eo.setStrategy(strategyEnum.name());
            eo.setFreq(freq.name());
            eo.setTsCode(tsCode);
            statParamService.remove(Wrappers.update(eo));
            eo.setM(m);
            eo.setN(n);
            eo.setOpenTime(closeData.get(0).getTradeTime());
            eo.setCloseTime(closeData.get(closeData.size() - 1).getTradeTime());
            eo.setMoney(aDouble);
            eo.setOpenPrice(closeData.get(0).getPrice());
            eo.setClosePrice(closeData.get(closeData.size() - 1).getPrice());
            eo.setPriceRate(
                    (eo.getClosePrice() - eo.getOpenPrice()) / eo.getOpenPrice() * 100
            );
            eo.setMoneyRate((aDouble - 1000000) / 1000000 * 100);
            statParamService.save(eo);

        }

        return aDouble;
    }

    public Double analysisEmaUpComplex(int ref, int ma, List<DataVo> closeData, boolean save, String tsCode, FreqEnum freq) {
        StrategyEnum strategyEnum = StrategyEnum.EMA_UP_COMPLEX;
        List<TradeVo> tradeVos = serviceCalc.calcEmaUpTradeComplex(closeData, 38, 54, ref, ma);
        tradeVos = tradeVos.stream().skip(50).collect(Collectors.toList());
        Double aDouble = stockTradeService.doTrade(tradeVos, save,tsCode, strategyEnum);

        if (save) {
            StatParamEo eo = new StatParamEo();
            eo.setStrategy(strategyEnum.name());
            eo.setFreq(freq.name());
            eo.setTsCode(tsCode);
            statParamService.remove(Wrappers.update(eo));
            eo.setM(ref);
            eo.setN(ma);
            eo.setOpenTime(closeData.get(0).getTradeTime());
            eo.setCloseTime(closeData.get(closeData.size() - 1).getTradeTime());
//            stockStatOptimizeService.remove(Wrappers.update(eo));

            eo.setMoney(aDouble);
            eo.setOpenPrice(closeData.get(0).getPrice());
            eo.setClosePrice(closeData.get(closeData.size() - 1).getPrice());
            eo.setPriceRate(
                    (eo.getClosePrice() - eo.getOpenPrice()) / eo.getOpenPrice() * 100
            );
            eo.setMoneyRate((aDouble - 1000000) / 1000000 * 100);
            statParamService.save(eo);

        }
        return aDouble;
    }

    public StockStatEo getTopOne(String tsCode, StrategyEnum strategyEnum) {
        IPage<StockStatEo> page = new Page<>(1, 1);
        IPage<StockStatEo> page1 = getBaseMapper().selectPage(page, Wrappers.<StockStatEo>lambdaQuery()
                .eq(StockStatEo::getTsCode,tsCode)
                .eq(StockStatEo::getStrategy,strategyEnum.name())
                .orderByDesc(StockStatEo::getMoney)
                );
        if (CollectionUtil.isNotEmpty(page1.getRecords())) {
            return page1.getRecords().get(0);
        }
        throw new RuntimeException("有误");
    }

    public Double analysisEmaRef0(int m, int n, List<DataVo> closeData, boolean save, String tsCode, FreqEnum freq) {
        StrategyEnum strategyEnum = StrategyEnum.EMA_REF0;
        List<TradeVo> tradeVos = serviceCalc.calcEmaRef0Trade(closeData, m, n);
        tradeVos = tradeVos.stream().skip(50).collect(Collectors.toList());
        Double aDouble = stockTradeService.doTrade(tradeVos, save,tsCode, strategyEnum);

        if (save) {
            StatParamEo eo = new StatParamEo();
            eo.setStrategy(strategyEnum.name());
            eo.setFreq(freq.name());
            eo.setTsCode(tsCode);
            statParamService.remove(Wrappers.update(eo));
            eo.setM(m);
            eo.setN(n);
            eo.setOpenTime(closeData.get(0).getTradeTime());
            eo.setCloseTime(closeData.get(closeData.size() - 1).getTradeTime());
//            stockStatOptimizeService.remove(Wrappers.update(eo));

            eo.setMoney(aDouble);
            eo.setOpenPrice(closeData.get(0).getPrice());
            eo.setClosePrice(closeData.get(closeData.size() - 1).getPrice());
            eo.setPriceRate(
                    (eo.getClosePrice() - eo.getOpenPrice()) / eo.getOpenPrice() * 100
            );
            eo.setMoneyRate((aDouble - 1000000) / 1000000 * 100);
            statParamService.save(eo);
        }
        return aDouble;
    }

    public Double analysisMaUp(int m, List<DataVo> closeData, boolean save, String tsCode, FreqEnum freq) {
        StrategyEnum strategyEnum = StrategyEnum.MA_UP;
        List<TradeVo> tradeVos = serviceCalc.calcMaUpTrade(closeData, m,0);
        tradeVos = tradeVos.stream().skip(50).collect(Collectors.toList());
        Double aDouble = stockTradeService.doTrade(tradeVos, save,tsCode, strategyEnum);

        if (save) {
            StatParamEo eo = new StatParamEo();
            eo.setStrategy(strategyEnum.name());
            eo.setFreq(freq.name());
            eo.setTsCode(tsCode);
            statParamService.remove(Wrappers.update(eo));
            eo.setM(m);
//            eo.setN(n);
            eo.setOpenTime(closeData.get(0).getTradeTime());
            eo.setCloseTime(closeData.get(closeData.size() - 1).getTradeTime());
//            stockStatOptimizeService.remove(Wrappers.update(eo));

            eo.setMoney(aDouble);
            eo.setOpenPrice(closeData.get(0).getPrice());
            eo.setClosePrice(closeData.get(closeData.size() - 1).getPrice());
            eo.setPriceRate(
                    (eo.getClosePrice() - eo.getOpenPrice()) / eo.getOpenPrice() * 100
            );
            eo.setMoneyRate((aDouble - 1000000) / 1000000 * 100);
            statParamService.save(eo);
        }
        return aDouble;
    }

    public Double analysisMaCross(int m,int n, List<DataVo> closeData, boolean save, String tsCode, FreqEnum freq) {
        StrategyEnum strategyEnum = StrategyEnum.MA_CROSS;
        List<TradeVo> tradeVos = serviceCalc.calcMaCrossTrade(closeData, m, n);
        tradeVos = tradeVos.stream().skip(50).collect(Collectors.toList());
        Double aDouble = stockTradeService.doTrade(tradeVos, save,tsCode, strategyEnum);

        if (save) {
            StatParamEo eo = new StatParamEo();
            eo.setStrategy(strategyEnum.name());
            eo.setFreq(freq.name());
            eo.setTsCode(tsCode);
            statParamService.remove(Wrappers.update(eo));
            eo.setM(m);
            eo.setN(n);
            eo.setOpenTime(closeData.get(0).getTradeTime());
            eo.setCloseTime(closeData.get(closeData.size() - 1).getTradeTime());
//            stockStatOptimizeService.remove(Wrappers.update(eo));

            eo.setMoney(aDouble);
            eo.setOpenPrice(closeData.get(0).getPrice());
            eo.setClosePrice(closeData.get(closeData.size() - 1).getPrice());
            eo.setPriceRate(
                    (eo.getClosePrice() - eo.getOpenPrice()) / eo.getOpenPrice() * 100
            );
            eo.setMoneyRate((aDouble - 1000000) / 1000000 * 100);
            statParamService.save(eo);
        }
        return aDouble;
    }

    public Double analysisMaPure(int m, List<DataVo> closeData, boolean save, String tsCode, FreqEnum freq) {
        StrategyEnum strategyEnum = StrategyEnum.MA_PURE;
        List<TradeVo> tradeVos = serviceCalc.calcMaPureTrade(closeData, m);
        tradeVos = tradeVos.stream().skip(50).collect(Collectors.toList());
        Double aDouble = stockTradeService.doTrade(tradeVos, save,tsCode, strategyEnum);

        if (save) {
            StatParamEo eo = new StatParamEo();
            eo.setStrategy(strategyEnum.name());
            eo.setFreq(freq.name());
            eo.setTsCode(tsCode);
            statParamService.remove(Wrappers.update(eo));
            eo.setM(m);
//            eo.setN(n);
            eo.setOpenTime(closeData.get(0).getTradeTime());
            eo.setCloseTime(closeData.get(closeData.size() - 1).getTradeTime());
//            stockStatOptimizeService.remove(Wrappers.update(eo));

            eo.setMoney(aDouble);
            eo.setOpenPrice(closeData.get(0).getPrice());
            eo.setClosePrice(closeData.get(closeData.size() - 1).getPrice());
            eo.setPriceRate(
                    (eo.getClosePrice() - eo.getOpenPrice()) / eo.getOpenPrice() * 100
            );
            eo.setMoneyRate((aDouble - 1000000) / 1000000 * 100);
            statParamService.save(eo);
        }
        return aDouble;
    }

    public Double analysis(int m, int n, List<DataVo> closeData, boolean save, String tsCode, FreqEnum freq, StrategyEnum strategy) {

        switch (strategy) {
            case EMA_UP:
                return analysisEmaUp(m, n, closeData, save, tsCode, freq);
            case MA_UP:
                return analysisMaUp(m, closeData, save, tsCode, freq);
            case EMA_REF0:
                return analysisEmaRef0(m, n, closeData, save, tsCode, freq);
            case MA_CROSS:
                return analysisMaCross(m, n, closeData, save, tsCode, freq);
            case MA_PURE:
                return analysisMaPure(m, closeData, save, tsCode, freq);
            case EMA_UP_COMPLEX:
                return analysisEmaUpComplex(m, n, closeData, save, tsCode, freq);
             default:
                 throw new RuntimeException("枚举有误 analysis "+strategy.name());
        }

    }

    public void delete(String tsCode, StrategyEnum strategy) {
        remove(Wrappers.update(new StockStatEo()
                .setTsCode(tsCode)
                .setStrategy(strategy.name())));
    }
}
